import {Component} from 'react';
import {DropTargetConnector, DropTargetMonitor} from 'react-dnd';

import store from '../store';
import {createView, acceptView} from '../views';

import {IView} from '../types/IView';
import {IDragItem} from './IDragItem';
import {ActionType} from '../store/ActionType';

/**
 * Specifies the drop target contract.
 * All methods are optional.
 */
export default {

  target: {
    hover(props: any, monitor: DropTargetMonitor, component: Component<any, any>) {
      console.info(props, monitor, component);

      // This is fired very often and lets you perform side effects in response to the
      // hover. You can't handle enter and leave here—if you need them, put
      // monitor.isOver() into collect() so you can just use
      // componentWillReceiveProps() to handle enter/leave. You can access the
      // coordinates if you need them
      const clientOffset = monitor.getClientOffset();
      // const componentRect = findDOMNode(component).getBoundingClientRect(); You can
      // check whether we're over a nested drop target
      const isJustOverThisOne = monitor.isOver({shallow: true});

      // You will receive hover() even for items for which canDrop() is false
      const canDrop = monitor.canDrop();
      // console.info(clientOffset, isJustOverThisOne, canDrop);
    },

    drop(props: any, monitor: DropTargetMonitor, component: Component<any, any>) {
      if (monitor.didDrop()) {
        // If you want, you can check whether some nested target already handled drop
        return;
      }

      if (!props.view) {
        return;
      }

      // Obtain the dragged item
      const item: IDragItem = monitor.getItem() as IDragItem;

      // 如果是拖到一个view 上面, 则是添加到它的子节点列表里面
      const view: IView = props.view;

      if (item.viewType) {
        //
        const newView = createView(item.viewType, view.designId);

        store.dispatch({
          type: ActionType.ADD_CHILD_VIEW,
          designId: view.designId,
          viewId: view.id,
          childView: newView
        });
      } else if (item.view) {
        store.dispatch({
          type: ActionType.MOVE_VIEW,
          designId: view.designId,
          viewId: view.id,
          childView: item.view
        });
      }

      // You can also do nothing and return a drop result, which will be available as
      // monitor.getDropResult() in the drag source's endDrag() method
      return {widget: true};
    },

    canDrop(props: any, monitor: DropTargetMonitor): boolean {
      if (!props.view || !props.view.children) {
        return false;
      }

      // Obtain the dragged item
      const item: IDragItem = monitor.getItem() as IDragItem;
      return acceptView(props.view.viewType, item.viewType || item.view.viewType);
    }
  },

  collect(connect: DropTargetConnector, monitor: DropTargetMonitor) {
    return {
      // Call this function inside render() to let React DnD handle the drag events:
      connectDropTarget: connect.dropTarget()
      /*// You can ask the monitor about the current drag state:
       isOver: monitor.isOver(),
       isOverCurrent: monitor.isOver({ shallow: true }),
       canDrop: monitor.canDrop(),
       itemType: monitor.getItemType()*/
    };
  }

};
